bitkeeper revision 1.1327.2.11 (426fb893OrpBVeRpaWJ0atIxlG4Hxw)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 27 Apr 2005 16:06:43 +0000 (16:06 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 27 Apr 2005 16:06:43 +0000 (16:06 +0000)
Add support for unix-domain sockets to consoles and the
event server.

Signed-off-by: Mike Wray <mike.wray@hp.com>
tools/python/xen/util/console_client.py
tools/python/xen/web/unix.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/console.py
tools/python/xen/xend/server/event.py
tools/python/xen/xm/create.py
tools/python/xen/xm/main.py

index 8bd3178eab4e925afc6242688595a9567fb593c2..c0acacfad39823d52cc8e564d1ed0726d43a7bd7 100644 (file)
@@ -57,9 +57,18 @@ def __send_to_sock(sock):
                     raise
     sys.exit(0)
 
-def connect(host,port):
-    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-    sock.connect((host,port))
+def connect(host, port, path=None):
+    # Try inet first. If 'path' is given and the error
+    # was connection refused, try unix-domain on 'path'.
+    try:
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        sock.connect((host, port))
+    except socket.error, err:
+        if (path is None) or (err[0] != errno.ECONNREFUSED):
+            raise
+        # Try unix-domain.
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        sock.connect(path)
 
     oattrs = tcgetattr(0)
     nattrs = tcgetattr(0)
@@ -86,7 +95,14 @@ def connect(host,port):
         __send_to_sock(sock)
 
 if __name__ == '__main__':
-    if len(sys.argv) != 3:
-        print sys.argv[0] + " <host> <port>"
+    argc = len(sys.argv)
+    if argc < 3 or argc > 4:
+        print >>sys.stderr, sys.argv[0], "<host> <port> [<path>]"
         sys.exit(1)
-    connect(str(sys.argv[1]),int(sys.argv[2]))
+    host = sys.argv[1]
+    port = int(sys.argv[2])
+    if argc > 3:
+        path = sys.argv[3]
+    else:
+        path = None
+    connect(host, port, path=path)
index d82ed0a6c3be98789c5f535a101520d1221d29be..7381816031dc8e36b7cb8e6581c25e88d92d2faf 100644 (file)
@@ -1,6 +1,7 @@
 import sys
 import socket
 import os
+import os.path
 
 from connection import *
 from protocol import *
@@ -15,18 +16,22 @@ class UnixListener(SocketListener):
         self.path = path
         
     def createSocket(self):
-        try:
-            os.unlink(self.path)
-        except SystemExit:
-            raise
-        except Exception, ex:
-            pass
+        pathdir = os.path.dirname(self.path)
+        if not os.path.exists(pathdir):
+            os.makedirs(pathdir)
+        else:
+            try:
+                os.unlink(self.path)
+            except SystemExit:
+                raise
+            except Exception, ex:
+                pass
         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
         sock.bind(self.path)
         return sock
 
     def acceptConnection(self, sock, protocol, addr):
-        return UnixServerConnection(sock, protocol, addr, self)
+        return UnixServerConnection(sock, protocol, self.path, self)
 
 class UnixClientConnection(SocketClientConnection):
 
index 74952487530aca9bf773c1f6f8c1f7e33e3f31f7..557c18ecdd99e65f7183aa8d3ffe5a6db655b4fc 100644 (file)
@@ -324,7 +324,7 @@ class Daemon:
             xroot = XendRoot.instance()
             log.info("Xend Daemon started")
             self.createFactories()
-            self.listenEvent(xroot)
+            event.listenEvent(self)
             self.listenChannels()
             servers = SrvServer.create()
             self.daemonize()
@@ -340,11 +340,6 @@ class Daemon:
     def createFactories(self):
         self.channelF = channel.channelFactory()
 
-    def listenEvent(self, xroot):
-        port = xroot.get_xend_event_port()
-        interface = xroot.get_xend_address()
-        return event.listenEvent(self, port, interface)
-
     def listenChannels(self):
         def virqReceived(virq):
             print 'virqReceived>', virq
index 1cd1bb5df0592eb5ab742c6cb2dfd29a0014e832..f366904d564e74f55759ad03a585d9ace6cda8b1 100755 (executable)
@@ -19,7 +19,7 @@ from messages import *
 from params import *
 
 class ConsoleProtocol(protocol.Protocol):
-    """Asynchronous handler for a console TCP socket.
+    """Asynchronous handler for a console socket.
     """
 
     def __init__(self, console, id):
@@ -36,10 +36,16 @@ class ConsoleProtocol(protocol.Protocol):
             self.loseConnection()
             return
         else:
+            if len(self.addr) == 2:
+                host = str(self.addr[0])
+                port = str(self.addr[1])
+            else:
+                host = 'localhost'
+                port = str(addr)
             log.info("Console connected %s %s %s",
-                     self.id, str(self.addr[0]), str(self.addr[1]))
+                     self.id, host, port)
             eserver.inject('xend.console.connect',
-                           [self.id, self.addr[0], self.addr[1]])
+                           [self.id, host, port])
 
     def dataReceived(self, data):
         if self.console.receiveInput(self, data):
@@ -50,7 +56,6 @@ class ConsoleProtocol(protocol.Protocol):
         return len(data)
 
     def connectionLost(self, reason=None):
-        print 'ConsoleProtocol>connectionLost>', reason
         log.info("Console disconnected %s %s %s",
                  str(self.id), str(self.addr[0]), str(self.addr[1]))
         eserver.inject('xend.console.disconnect',
@@ -60,22 +65,7 @@ class ConsoleProtocol(protocol.Protocol):
     def loseConnection(self):
         self.transport.loseConnection()
 
-class ConsoleFactory(protocol.ServerFactory):
-    """Asynchronous handler for a console server socket.
-    """
-    protocol = ConsoleProtocol
-    
-    def __init__(self, console, id):
-        #protocol.ServerFactory.__init__(self)
-        self.console = console
-        self.id = id
-
-    def buildProtocol(self, addr):
-        proto = self.protocol(self.console, self.id)
-        proto.factory = self
-        return proto
-
-class ConsoleDev(Dev):
+class ConsoleDev(Dev, protocol.ServerFactory):
     """Console device for a domain.
     Does not poll for i/o itself, but relies on the domain to post console
     output and the connected TCP sockets to post console input.
@@ -96,7 +86,9 @@ class ConsoleDev(Dev):
         self.obuf = xu.buffer()
         self.ibuf = xu.buffer()
         self.channel = None
-        self.listener = None
+        self.listening = False
+        self.unix_listener = None
+        self.tcp_listener = None
         
         console_port = sxp.child_value(self.config, "console_port")
         if console_port is None:
@@ -188,9 +180,15 @@ class ConsoleDev(Dev):
         try:
             self.lock.acquire()
             self.status = self.STATUS_CLOSED
+            self.listening = False
             if self.conn:
                 self.conn.loseConnection()
-            self.listener.stopListening()
+            if self.tcp_listener:
+                self.tcp_listener.stopListening()
+                self.tcp_listener = None
+            if self.unix_listener:
+                self.unix_listener.stopListening()
+                self.unix_listener = None
         finally:
             self.lock.release()
 
@@ -201,16 +199,28 @@ class ConsoleDev(Dev):
             self.lock.acquire()
             if self.closed():
                 return
-            if self.listener:
+            if self.listening:
                 pass
             else:
+                self.listening = True
                 self.status = self.STATUS_LISTENING
-                cf = ConsoleFactory(self, self.id)
-                interface = xroot.get_console_address()
-                self.listener = reactor.listenTCP(self.console_port, cf, interface=interface)
+                if xroot.get_xend_unix_server():
+                    path = '/var/lib/xend/console-%s' % self.console_port
+                    self.unix_listener = reactor.listenUNIX(path, self)
+                if xroot.get_xend_http_server():
+                    interface = xroot.get_console_address()
+                    self.tcp_listener = reactor.listenTCP(self.console_port, self, interface=interface)
         finally:
             self.lock.release()
 
+    def buildProtocol(self, addr):
+        """Factory function called to create the protocol when a connection is accepted
+        by listenTCP.
+        """
+        proto = ConsoleProtocol(self, self.id)
+        proto.factory = self
+        return proto
+
     def connect(self, addr, conn):
         """Connect a TCP connection to the console.
         Fails if closed or already connected.
index ebd4d6fd51783ca69bf99652fcd066e3eaad6e9c..ce76c149b03985d84ffc0a1fb6a9bf64ff79ff00 100644 (file)
@@ -11,7 +11,7 @@ from xen.xend import EventServer
 eserver = EventServer.instance()
 from xen.xend.XendError import XendError
 
-from xen.xend import XendRoot
+from xen.xend import XendRoot; xroot = XendRoot.instance()
 
 DEBUG = 1
 
@@ -165,7 +165,7 @@ class EventProtocol(protocol.Protocol):
 
     def op_log_stderr(self, name, v):
         mode = v[1]
-        logging = XendRoot.instance().get_logging()
+        logging = xroot.get_logging()
         if mode == 'on':
             logging.addLogStderr()
         else:
@@ -181,21 +181,23 @@ class EventProtocol(protocol.Protocol):
         import controller
         controller.DEBUG = (mode == 'on')
 
-class EventFactory(protocol.Factory):
+class EventFactory(protocol.ServerFactory):
     """Asynchronous handler for the event server socket.
     """
-    protocol = EventProtocol
-    service = None
 
     def __init__(self, daemon):
-        #protocol.Factory.__init__(self)
+        #protocol.ServerFactory.__init__(self)
         self.daemon = daemon
 
     def buildProtocol(self, addr):
-        proto = self.protocol(self.daemon)
-        proto.factory = self
-        return proto
+        return EventProtocol(self.daemon)
 
-def listenEvent(daemon, port, interface):
+def listenEvent(daemon):
     factory = EventFactory(daemon)
-    return reactor.listenTCP(port, factory, interface=interface)
+    if xroot.get_xend_unix_server():
+        path = '/var/lib/xend/event-socket'
+        reactor.listenUNIX(path, factory)
+    if xroot.get_xend_http_server():
+        port = xroot.get_xend_event_port()
+        interface = xroot.get_xend_address()
+        reactor.listenTCP(port, factory, interface=interface)
index bd8f81ae3e6d2d70b0b1f5af97d075a830dbde46..82fd0b7a2212179102feb682ff66cf90d635a985 100644 (file)
@@ -593,7 +593,8 @@ def main(argv):
     else:
         (dom, console) = make_domain(opts, config)
         if opts.vals.console_autoconnect:
-            console_client.connect('localhost', console)
+            path = "/var/lib/xend/console-%s" % console
+            console_client.connect('localhost', console, path=path)
         
 if __name__ == '__main__':
     main(sys.argv)
index a3fb9c75f3f79f1f65f5db295971722fb21675b1..e1494bc3a1028aaf0881b8ecd6cb073c1b42889e 100644 (file)
@@ -644,7 +644,8 @@ class ProgConsole(Prog):
             self.err("No console information")
         port = sxp.child_value(console, "console_port")
         from xen.util import console_client
-        console_client.connect("localhost", int(port))
+        path = "/var/lib/xend/console-%s" % port
+        console_client.connect("localhost", int(port), path=path)
 
 xm.prog(ProgConsole)